#include "FileImage.h"

CFileImage::CFileImage(void):m_hFile(INVALID_HANDLE_VALUE)
{
}

CFileImage::CFileImage(LPCTSTR lpszFileName):m_hFile(INVALID_HANDLE_VALUE)
{
    m_strFileName = lpszFileName;
}

CFileImage::~CFileImage(void)
{
}

VOID 
CFileImage::SetFile(
    IN LPCTSTR lpszFile
)
{
    m_strFileName = lpszFile;
}

VOID
CFileImage::SetFile(
    IN tstring& strFile
)
{
    m_strFileName = strFile;
}

BOOL
CFileImage::PeOpen()
{
    HANDLE hFile;

    //
    //  set not mapped for file.
    //
    
    SetOpenMode(FALSE);
    if (m_strFileName.empty()){
        return FALSE;
    }
    hFile = CreateFile(m_strFileName.c_str(), GENERIC_READ, 0, 
            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hFile){
        
        //
        //  TODO log the error info.
        //
        
        return FALSE;
    }

    m_hFile = hFile;
    return TRUE;
}

FORCEINLINE
BOOL
CFileImage::IsFileInitial()
{
    if (m_strFileName.empty() || INVALID_HANDLE_VALUE == m_hFile){
        return FALSE;
    }
    return TRUE;
}

BOOL
CFileImage::PeRead(
    IN ULONGLONG Offset, 
    OUT PVOID Buffer, 
    IN ULONG Length
)
{
    LARGE_INTEGER li;
    ULONG nRead;

    if (!Buffer || !Length){
        return FALSE;
    }
    if (!IsFileInitial()){
        return FALSE;
    }
    
    li.QuadPart = Offset;

    //
    //  set pointer.
    //
    
    li.LowPart = SetFilePointer(m_hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
    if (INVALID_SET_FILE_POINTER == li.LowPart &&
        NO_ERROR == GetLastError()){
        
        //
        //  TODO log error
        //
        
        return FALSE;
    }
    
    //
    //  read the pe file.
    //
    
    if (!ReadFile(m_hFile, Buffer, Length, &nRead, NULL)){
        return FALSE;
    }

    if (nRead != Length){
        return FALSE;
    }

    return TRUE;
}

BOOL
CFileImage::PeWrite(
    IN ULONGLONG Offset, 
    IN PVOID Buffer, 
    IN ULONG Length
)
{
    
    //
    //  no support yet.
    //
    
    return FALSE;
}

VOID
CFileImage::PeClose()
{
    if (!IsFileInitial()){
        return;
    }

    CloseHandle(m_hFile);
    m_hFile = NULL;
    m_strFileName.clear();

}